
package org.jma.app.ewisdom.entities;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Vector;

import org.jma.app.ewisdom.exceptions.ContentException;
import org.jma.lib.soap.utils.XMLSerializable;

import com.thoughtworks.xstream.XStream;

/**
 * Content class maintains a Documentation Index structure. It stores a reference
 * to its parent node, the title and a complete path.<br>
 * @author Jesus Mari, jesmari@ono.com
 * @version 1.0
 * @since 1.0
 */
public class Content extends EntityWithACL implements Cloneable, Serializable,XMLSerializable {
	
	String parent=null;
	String comment;
	String title;
	String stringHashCode;
	protected String path;
	
	
	
	ArrayList contents= new ArrayList();
	ArrayList files= new ArrayList();
	
	
	/**
	 * Class constructor. Creates an instance of a <code>Content</code>.
	 * @param title Title of the Content. 
	 * @param parent Reference to a superior Content. Hash code generated using the path
	 */
	public Content(String title,String parent){
		this.title=title;
		this.parent=parent;
		this.path=title;
		this.hashCode();
	}
	


	/**
	 * Adds a new Content to the current content, assigns as its parent the current content <code>CID</code>.
	 * The new Content inherits the ACL of its parent. 
	 * @param pos position must exist (position in the internal ArrayList.  
	 * @param title title of the child Content.
	 * @param user user name owner of this new Content. 
	 * @return the new Content instance.
	 * @throws a {@link ContentException}
	 */
	public Content addContentsBranch(int pos, String title, String user) throws ContentException{
		if ((title ==null) || ("".equals(title))|| (user ==null) || ("".equals(user))) 
			throw new ContentException("specify user and title");
		Content c= new Content(title,this.title);
		c.path=this.path+'/'+title;
		//Only stores the title because the content will be stored in a DHT!!
		contents.add(pos,c.getStringHashCode());
		return c;
	}
	
	/**
	 * Removes the Content allocated in position pos
	 * @param pos the position.
	 */
	public void removeContentsBranch(int pos){
		contents.remove(pos);
	}
	
	/**
	 * Gets the Content reference (CID) allocated in the position pos
	 * @param pos the position
	 * @return a Content reference (CID)
	 */
	public String getContentsBranch(int pos){
		return (String)contents.get(pos);
	}
	
	/**
	 * Gets the reference(CID) to the parent Content or the string "null" if it is a root Content 
	 * @return a Content reference to its parent(CID)
	 */
	public String getParent(){return this.parent;}

	/**
	 * gets the title 
	 * @return title string
	 */
	public String getTitle(){return title;}
	
	/**
	 * Adds a new {@link FileDescriptor} to the current content, assigns as its parent the current content <code>CID</code>.
	 * The new FILE inherits the ACL of its parent. 
	 * @param pos position must exist (position in the internal ArrayList.  
	 * @param fileName file name.
	 * @return an instance of {@link FileDescriptor}
	 * @throws throws {@link ContentException}
	 */
	public FileDescriptor addFile(int pos, String fileName) throws ContentException{
		if ((fileName ==null) || ("".equals(fileName))) 
			throw new ContentException("specify user and file name");
		//Only stores the title because the content will be stored in a DHT!!
		FileDescriptor fd=new FileDescriptor();
		fd.path=this.path+'/'+fileName;
		fd.setACL(this.getACLClone());
		fd.setParent(this.getStringHashCode());
		fd.setTitle(fileName);
		fd.hashCode();
		files.add(pos,fd.getStringHashCode());
		return fd;
	}
	
	/**
	 * Removes the FileDescriptor allocated in position pos
	 * @param pos the position.
	 */
	public void removeFile (int pos){
		files.remove(pos);
	}
	

	/**
	 * Allows to put a comment about the Content 
	 * @param comment String containing the comment
	 */
	public void setComment(String comment){
		this.comment=comment;	
	}
	
	
	/**
	 * @see org.jma.lib.soap.utils.XMLSerializable
	 */
    public String serializeToXML() {
    	XStream xstream = new XStream();
    	return xstream.toXML(this);
    }

    /**
     * Return the number of child Contents
     * @return number of Content branches
     */
	public int getNumberOfBranches() {		
		return contents.size();
	}
	
	/**
	 * @see java.lang.Cloneable
	 */
	public Content clone() throws CloneNotSupportedException{	
		return (Content)super.clone();
	}
	
	/**
	 * Overrides the equals method from Object class. Two Content will be equals if
	 * their paths are equal.
	 */
	public boolean equals(Object content){		
		if (this.path==null && ((Content)content).getPath()==null) return true;
		else return (this.path.equals(((Content)content).getPath()));		
	}
	
	/**
	 * Returns the complete Path inside the index
	 * @return a string with the path
	 */
	public String getPath(){
		if (this.path==null) return ""; else return this.path;
	}
	
	/**
	 * Only for xml serialization purpose
	 * @param path
	 */
	public void setPath(String path){
		this.path=path;
	}
	/**
	 * HashCode in string form
	 * @return Hashcode
	 */
	public String getStringHashCode(){
		return stringHashCode;
	}
	
	/**
	 * Only for xml serialization purpose 
	 * @param stringHashCode
	 */
	public void setStringHashCode(String stringHashCode){
		this.stringHashCode=stringHashCode;
	}
	
	
	/**
	 * calculates its HashCode  
	 * @return Hashcode
	 */
	public int hashCode() {
			int result=0;
	        result = (path != null ? path.hashCode() : 0);
	        stringHashCode=""+result;
	        return result;
	 }
}
